/**
* \file		Carte.c
* \brief	Code des fonctions du module Carte
* \details	C'est ici qu'est le code des accesseurs, mutateurs ainsi que
*		la fonction de test vérifant le bon fonctionnement du module
*		Carte.
*		Une description de la structure Carte est fournie à
*		la rubrique \link Carte.h
*/

/* voir si on garde tous les includes */
#include "Carte.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <time.h>


/*========================== Gestion de la mémoire ==========================*/

void initCarte(Carte *pcarte, TabTerrains *ptableauTerr)
{
   int i,j,k;
   unsigned int tailleX, tailleY, tailleZ;
   Terrain *terrIni;
   char *nomTerrIniSurf = {"terreSurf"};
   char *nomTerrIniSout = {"terreSout"};
   Case *caseAct;

   /* allocation de la première dimension du tableau */
   tailleX = getXCarte(pcarte);
   pcarte->tab = malloc(tailleX * sizeof(*pcarte->tab));

   /* allocation de la deuxième dimension du tableau */
   tailleY = getYCarte(pcarte);
   for(i=0;i<tailleX;i++)
	{
	   pcarte->tab[i] = malloc(tailleY * sizeof(**pcarte->tab));
	}

   /* allocation de la troisième dimension du tableau */
   tailleZ = getZCarte(pcarte);
   for(i=0;i<tailleX;i++)
	{
	   for(j=0;j<tailleY;j++)
		{
		   pcarte->tab[i][j] = malloc(tailleZ * sizeof(***pcarte->tab));
		}
	}


   /* mise à zéro des terrains : terrains en sous-sol */
   terrIni = rechercheTabTerrains(ptableauTerr, nomTerrIniSout);
   for(k=0;k<tailleZ;k++)
	{
	   for(i=0;i<tailleX;i++)
		{
		   for(j=0;j<tailleY;j++)
			{
			   caseAct=getCaseCarte(pcarte, i, j, k);
			   initCase(caseAct, tailleX, tailleY, tailleZ);
			   setTerrainCase(caseAct, terrIni);
			   setXCase(caseAct, i, tailleX-1);
			   setYCase(caseAct, j, tailleY-1);
			   setZCase(caseAct, k, tailleZ-1);
			}
		}
	}

   /* mise à zéro des terrains : terrains de surface */
   terrIni = rechercheTabTerrains(ptableauTerr, nomTerrIniSurf);

   for(i=0;i<tailleX;i++)
	{
	   for(j=0;j<tailleY;j++)
		{
		   caseAct=getCaseCarte(pcarte, i, j, 0);
		   initCase(caseAct, tailleX, tailleY, tailleZ);
		   setTerrainCase(caseAct, terrIni);
		   setXCase(caseAct, i, tailleX-1);
		   setYCase(caseAct, j, tailleY-1);
		   setZCase(caseAct, 0, tailleZ-1);
		}

	}

   for(k=0;k<tailleZ;k++)
	{
	   for(i=0;i<tailleX;i++)
		{
		   for(j=0;j<tailleY;j++)
			{
			   setCasesAdjacentesCarte(pcarte, i, j, k, ptableauTerr);
			}
		}
	}




}

void creerCarte(Carte **pcarte, unsigned int x, unsigned int y, unsigned int z, TabTerrains *ptableauTerr)
{
   *pcarte = (Carte *)malloc(sizeof(Carte));
   setXCarte(*pcarte,x);
   setYCarte(*pcarte,y);
   setZCarte(*pcarte,z);

   initCarte(*pcarte,ptableauTerr);

}

void libereCarte(Carte *pcarte)
{
   unsigned int tailleX, tailleY, tailleZ, i, j, k;
   Case *pcase;

   tailleX = getXCarte(pcarte);
   tailleY = getYCarte(pcarte);
   tailleZ = getZCarte(pcarte);

   for(i=0; i<tailleX; i++)
	{
	   for(j=0; j<tailleY; j++)
		{
		   for(k=0; k<tailleZ; k++)
			{
			   pcase = getCaseCarte(pcarte, i, j, k);
			   libereCase(pcase);
			}
		}
	}



   for(i=0; i<tailleX ;i++)
	{
	   for(j=0; j<tailleY; j++)
		{
		   free(pcarte->tab[i][j]);
		}
	   free(pcarte->tab[i]);
	}
   free(pcarte->tab);
}

void detruireCarte(Carte *pcarte)
{
   libereCarte(pcarte);
   free(pcarte);
   pcarte = NULL;
}

/*==============================Accesseurs===============================*/

unsigned int getXCarte(const Carte *pcarte)
{
   return pcarte->x;
}

unsigned int getYCarte(const Carte *pcarte)
{
   return pcarte->y;
}

unsigned int getZCarte(const Carte *pcarte)
{
   return pcarte->z;
}

Case *getCaseCarte(const Carte *pcarte, unsigned int coordX, unsigned int coordY, unsigned int coordZ)
{
   return &pcarte->tab[coordX][coordY][coordZ];
}

Case **getCasesAdjacentesCarte(const Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ)
{
   Case *caseTemp;
   caseTemp = getCaseCarte(pcarte,coordX,coordY,coordZ);
   return getCasesAdjCase(caseTemp);
}

Terrain *getTerrainCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ)
{
   return pcarte->tab[coordX][coordY][coordZ].terrain;
}

Production *getProdCaseCarte(const Carte *pcarte, const unsigned int coordX, const unsigned int coordY, const unsigned int coordZ)
{
   Case *caseTemp;
   caseTemp = getCaseCarte(pcarte,coordX,coordY,coordZ);
   return getProdCase(caseTemp);   
}

char *getNomProdCaseCarte(const Carte *pcarte, const unsigned int coordX, const unsigned int coordY, const unsigned int coordZ)
{
   Case *caseTemp;
   caseTemp = getCaseCarte(pcarte,coordX,coordY,coordZ);
   return getNomProdCase(caseTemp);
}

int getPourcentageProdCaseCarte(const Carte *pcarte, const unsigned int coordX, const unsigned int coordY, const unsigned int coordZ)
{
   Case *caseTemp;
   caseTemp = getCaseCarte(pcarte,coordX,coordY,coordZ);
   return getPourcentageProdCase(caseTemp);
}

int getVitesseProdCaseCarte(const Carte *pcarte, const unsigned int coordX, const unsigned int coordY, const unsigned int coordZ)
{
   Case *caseTemp;
   caseTemp = getCaseCarte(pcarte,coordX,coordY,coordZ);
   return getVitesseProdCase(caseTemp);
}

/*============================== Mutateurs ==============================*/

void setXCarte(Carte *pcarte, unsigned int nouvX)
{
   pcarte->x = nouvX;
}

void setYCarte(Carte *pcarte, unsigned int nouvY)
{
   pcarte->y = nouvY;
}

void setZCarte(Carte *pcarte, unsigned int nouvZ)
{
   pcarte->z = nouvZ;
}

void setCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, Case *nouvCase)
{
   unsigned int xMax, yMax,zMax;
   Case caseAff;
   Case *caseAff2;
   xMax = getXCarte(pcarte);
   yMax = getYCarte(pcarte);
   zMax = getZCarte(pcarte);

   caseAff2 = getCaseCarte(pcarte,coordX,coordY,coordZ);
   caseAff = (*getCaseCarte(pcarte,coordX,coordY,coordZ));
   setTerrainCase(caseAff2, getTerrainCase(nouvCase));

   setNbPersCase(caseAff2, getNbPersCase(nouvCase));
   setTraversableCase(&caseAff, getTraversableCase(nouvCase));
   setXCase(caseAff2, getXCase(nouvCase), xMax);
   setYCase(caseAff2, getYCase(nouvCase), yMax);
   setZCase(caseAff2, getZCase(nouvCase), zMax);
}

void setTerrainCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, Terrain *pnouvTerrain)
{
   Case *pcaseAff;
   pcaseAff = getCaseCarte(pcarte, coordX,coordY,coordZ);
   setTerrainCase(pcaseAff, pnouvTerrain);
}

void setNouvProdCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, char *nomProd)
{
   Case *pcaseAff;
   pcaseAff = getCaseCarte(pcarte, coordX,coordY,coordZ);

  /* Si une production existe déjà, la détruire */
   if(getProdCaseCarte(pcarte, coordX,coordY,coordZ) != NULL)
	{
	   enleveProdCase(pcaseAff);
	}

   /* Attribuer la nouvelle production */
   setNouvProdCase(pcaseAff, nomProd);
}

void ajoutePourcentageProdCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, int pourcent)
{
   Case *pcaseAff;
   pcaseAff = getCaseCarte(pcarte, coordX,coordY,coordZ);

   ajoutePourcentageProdCase(pcaseAff, pourcent);   
}

void ajouteVitesseProdCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, int vitesse)
{
   Case *pcaseAff;
   pcaseAff = getCaseCarte(pcarte, coordX,coordY,coordZ);

   ajouteVitesseProdCase(pcaseAff, vitesse);   
}

/*===============================Manipulation================================*/

void setCasesAdjacentesCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, const TabTerrains *ptableauTerr)
{
   int i,j,k,x,y;
   Case *caseInter;
   Case *caseActuelle;
   unsigned int xMax,yMax;

   caseActuelle = getCaseCarte(pcarte, coordX, coordY, coordZ);
   xMax = getXCarte(pcarte) - 1;
   yMax = getYCarte(pcarte) - 1;

   if(coordX == 0)
	{
	   if(coordY == 0)
		{
		   /* case haut gauche */
		   caseActuelle->casesAdj = (Case**)malloc(4*sizeof(Case*));
		   setXAdjCase(caseActuelle, 4);
		   k = 0;
		   for(i=0;i<2;i++)
			{
			   for(j=0;j<2;j++)
				{
				   x=(int)coordX+i;
				   y=(int)coordY+j;
				   caseInter=getCaseCarte(pcarte,x,y,coordZ);
				   setIemeCaseAdjCase(caseActuelle, k, caseInter);
				   k++;
				}
			}
		}
	   else
		{
		   if(coordY == yMax)
			{
			   /* case bas gauche */
			   caseActuelle->casesAdj = (Case**)malloc(4*sizeof(Case*));
			   setXAdjCase(caseActuelle, 4);
			   k = 0;
			   for(i=0;i<2;i++)
				{
				   for(j=0;j<2;j++)
					{
					   x=(int)coordX+i;
					   y=(int)coordY+(j-1);
					   caseInter=getCaseCarte(pcarte,x,y,coordZ);
				   setIemeCaseAdjCase(caseActuelle, k, caseInter);
				   k++;
					}
				}

			}

		   else
			{
			   /* case à gauche */
			   caseActuelle->casesAdj = (Case**)malloc(6*sizeof(Case*));
			   setXAdjCase(caseActuelle, 6);
			   k=0;
			   for(i=0;i<2;i++)
				{
				   for(j=0;j<3;j++)
					{
					   x=(int)coordX+i;
					   y=(int)coordY+(j-1);
					   caseInter=getCaseCarte(pcarte,x,y,coordZ);
					   setIemeCaseAdjCase(caseActuelle, k, caseInter);
					   k++;
					}
				}

			}
		}
	}
   else 
	{
	   if(coordX == xMax)
		{
		   if(coordY == 0)
			{
			   /* case haut droite */
			   caseActuelle->casesAdj = (Case**)malloc(4*sizeof(Case*));
			   setXAdjCase(caseActuelle, 4);
			   k=0;
			   for(i=0;i<2;i++)
				{
				   for(j=0;j<2;j++)
					{
					   x=(int)coordX+(i-1);
					   y=(int)coordY+j;
					   caseInter=getCaseCarte(pcarte,x,y,coordZ);
					   setIemeCaseAdjCase(caseActuelle, k, caseInter);
					   k++;
					}
				}

			}
		   else
			{
			   if(coordY == yMax)
				{
				   /* case bas droite */
				   caseActuelle->casesAdj = (Case**)malloc(4*sizeof(Case*));
				   setXAdjCase(caseActuelle, 4);
				   k=0;
				   for(i=0;i<2;i++)
					{
					   for(j=0;j<2;j++)
						{
						   x=(int)coordX+(i-1);
						   y=(int)coordY+(j-1);
						   caseInter=getCaseCarte(pcarte,x,y,coordZ);
						   setIemeCaseAdjCase(caseActuelle, k, caseInter);
						   k++;
						}
					}

				}
			   else
				{
				   /* case à droite */
				   caseActuelle->casesAdj = (Case**)malloc(6*sizeof(Case*));
				   setXAdjCase(caseActuelle, 6);
				   k=0;
				   for(i=0;i<2;i++)
					{
					   for(j=0;j<3;j++)
						{
						   x=(int)coordX+(i-1);
						   y=(int)coordY+(j-1);
						   caseInter=getCaseCarte(pcarte,x,y,coordZ);
						   setIemeCaseAdjCase(caseActuelle, k, caseInter);
						   k++;
						}
					}

				}
			}

		}
	   else
		{
		   if(coordY == 0)
			{
			   /* case en haut */
			   caseActuelle->casesAdj = (Case**)malloc(6*sizeof(Case*));
			   setXAdjCase(caseActuelle, 6);
			   k=0;
			   for(j=0;j<3;j++)
				{
				   for(i=0;i<2;i++)
					{
					   x=(int)coordX+(j-1);
					   y=(int)coordY+i;
					   caseInter=getCaseCarte(pcarte,x,y,coordZ);
					   setIemeCaseAdjCase(caseActuelle, k, caseInter);
					   k++;
					}
				}

			}
		   else
			{
			   if(coordY == yMax)
				{
				   /* case en bas */
				   caseActuelle->casesAdj = (Case**)malloc(6*sizeof(Case*));
				   setXAdjCase(caseActuelle, 6);
				   k=0;
				   for(i=0;i<3;i++)
					{
					   for(j=0;j<2;j++)
						{
						   x=(int)coordX+(i-1);
						   y=(int)coordY+(j-1);
						   caseInter=getCaseCarte(pcarte,x,y,coordZ);
						   setIemeCaseAdjCase(caseActuelle, k, caseInter);
						   k++;
						}
					}

				}
			   else
				{
				   /* case pas au bord */
				   caseActuelle->casesAdj = (Case**)malloc(9*sizeof(Case*));
				   setXAdjCase(caseActuelle, 9);
				   k=0;
				   for(i=0;i<3;i++)
					{
					   for(j=0;j<3;j++)
						{
						   x=(int)coordX+(i-1);
						   y=(int)coordY+(j-1);
						   caseInter=getCaseCarte(pcarte,x,y,coordZ);
						   setIemeCaseAdjCase(caseActuelle, k, caseInter);
						   k++;
						}
					}
				}
			}

		}
	}

}

void planterGrainesCarte(Carte *pcarte, unsigned int nbGraines, unsigned int z, Terrain *pnouvTerrain, unsigned int tailleMax)
{
   unsigned int xAlea, yAlea, maxX, maxY, i;

   for(i=0; i<nbGraines; i++)
	{
	   maxX = getXCarte(pcarte)-1;
	   maxY = getYCarte(pcarte)-1;
	   xAlea = rand()%maxX+1;
	   yAlea = rand()%maxY+1;

	   pousseGraineCarte(pcarte, xAlea, yAlea, z, tailleMax, pnouvTerrain);
	}
}

void ajusteCoordCarte(unsigned int *x, unsigned int *y, unsigned int xMax, unsigned int yMax)
{
   if(*x<0)
	{
	   *x = 0;
	}

   if(*y<0)
	{
	   *y = 0;
	}

   if(*x > xMax)
	{
	   *x = xMax;
	}

   if(*y>yMax)
	{
	   *y = yMax;
	}
}

void pousseGraineCarte(Carte *pcarte, unsigned int xDep, unsigned int yDep, unsigned int z, unsigned int nbMax, Terrain *terrGraine)
{
   unsigned int x = xDep;
   unsigned int y = yDep;
   int pas = 1;
   int i,j;
   unsigned int xMax, yMax; /* coordonnées maximales pour la case à changer */
   int nbActuel=1; 	/* nombre actuel de cases qui ont été changées */

   char hautDroit = 'o'; /* équivalent booléen : est-on en train d'aller vers
			le haut ou vers la droite ? Si oui, hautDroit vaut o ;
			si non, hautDroit vaut n */

   int nbAlea;

   /* Probabilité que cette case contienne le nouveau terrain : début à 100
puis baisse au fur et à mesure qu'on change une case */
   int proba = 100;
   int varProba = (proba - 30)/nbMax;

   xMax = getXCarte(pcarte) - 1;
   yMax = getYCarte(pcarte) - 1;

   /* Remplissage de la première case */
   setTerrainCaseCarte(pcarte, x,y,z, terrGraine);

   /* Parcours en spirale autour de la graine et modification le cas échéant */
   while(nbActuel < nbMax)
	{
	   /* On monte ou on descend */
	   for(i=0;i<pas;i++)
		{
		   if(hautDroit == 'o')
			{
			   x--;
			}
		   else
			{
			   x++;
			}

		   /* tirage aléatoire : change-t-on la case ? */
		   nbAlea = rand()%100;

		   if ((nbAlea<=proba)&&(nbActuel < nbMax))
			{
			   ajusteCoordCarte(&x, &y, xMax, yMax);
			   setTerrainCaseCarte(pcarte,x,y,z,terrGraine);
			   nbActuel++;
			   proba = proba - varProba;
			}
		}

	   /* on va à droite ou à gauche */
	   for(j=0; j<pas; j++)
		{

		if(hautDroit == 'o')
			{
			   y++;
			}
		else
			{
			   y--;
			}

		   nbAlea = rand()%100;
		   
		   if ((nbAlea<=proba)&&(nbActuel < nbMax))
			{
			   ajusteCoordCarte(&x, &y, xMax, yMax);
			   setTerrainCaseCarte(pcarte,x,y,z,terrGraine);
			   nbActuel++;
			   proba = proba - varProba;
			}
		}
	   pas++;

		if(hautDroit == 'o')
			{
			   hautDroit = 'n';
			}
		else
			{
			   hautDroit = 'o';
			}

	}

}




char caseVoisineDeTerrainCarte(Carte *pcarte, unsigned int x, unsigned int y,unsigned int z, char *nomTerrain, const TabTerrains *ptableauTerr)
{
   Case **tabCasesAdj;
   Case *caseDemandee;
   Terrain *compTerr;
   int i;
   unsigned int nb;

   tabCasesAdj = getCasesAdjacentesCarte(pcarte,x,y,z);

   caseDemandee = getCaseCarte(pcarte,x,y,z);
   nb = getXAdjCase(caseDemandee);

   for(i=0; i<nb; i++)
	{
	   compTerr = getTerrainCase(tabCasesAdj[i]);
	   if(cmpTerrainNom(compTerr, nomTerrain) == 1)
		{
		   return 1;
		}
	}

   return 0;
}


void sableCarte(Carte *pcarte, TabTerrains *ptableauTerr)
{
   unsigned int x, y;
   int i,j;
   Terrain *compTerr;
   Terrain *sable = rechercheTabTerrains(ptableauTerr, "sable");
   x = getXCarte(pcarte);
   y = getYCarte(pcarte);

   for(i=0;i<x;i++)
	{
	   for(j=0;j<y;j++)
		{
		   compTerr = getTerrainCaseCarte(pcarte,i,j,0);
		   if(cmpTerrainNom(compTerr, "eau") == 0)
			{
			   if(caseVoisineDeTerrainCarte(pcarte, i, j,0, "eau", ptableauTerr))
				{
				   setTerrainCaseCarte(pcarte, i,j,0,sable);
				}

			}
		}
	}
}


void pousseGraineProdCarte(Carte *pcarte, unsigned int xDep, unsigned int yDep, unsigned int z, unsigned int nbMax, char *nomProdGraine, char *nomTerrainTabou)
{
   Terrain *compTerr;
   unsigned int x = xDep;
   unsigned int y = yDep;
   int pas = 1;
   int i,j;
   unsigned int xMax, yMax; /* coordonnées maximales pour la case à changer */
   int nbActuel=1; 	/* nombre actuel de cases qui ont été changées */

   char hautDroit = 'o'; /* équivalent booléen : est-on en train d'aller vers
			le haut ou vers la droite ? Si oui, hautDroit vaut o ;
			si non, hautDroit vaut n */

   int nbAlea;

   /* Probabilité que cette case contienne la nouvelle production : début à
100 puis baisse au fur et à mesure qu'on change une case */
   int proba = 100;
   int varProba = (proba - 30)/nbMax;

   xMax = getXCarte(pcarte) - 1;
   yMax = getYCarte(pcarte) - 1;

   /* Remplissage de la première case */
   setNouvProdCaseCarte(pcarte, x,y,z, nomProdGraine);

   /* Parcours en spirale autour de la graine et modification le cas échéant */
   while(nbActuel < nbMax)
	{
	   /* On monte ou on descend */
	   for(i=0;i<pas;i++)
		{
		   if(hautDroit == 'o')
			{
			   x--;
			}
		   else
			{
			   x++;
			}

		   /* tirage aléatoire : change-t-on la case ? */
		   nbAlea = rand()%100;

		   if ((nbAlea<=proba)&&(nbActuel < nbMax))
			{
			   ajusteCoordCarte(&x, &y, xMax, yMax);
			   compTerr = getTerrainCaseCarte(pcarte, x,y,z);

			   /* condition de remplissage : le terrain n'est pas 				   du sable et n'est pas incompatible avec la
			   production à placer */
			   if((0 == cmpTerrainNom(compTerr, "sable"))&&
				(0 == cmpTerrainNom(compTerr, nomTerrainTabou)))
				{
				   setNouvProdCaseCarte(pcarte,x,y,z,nomProdGraine);
				}

			   /* Dans tous les cas, pour éviter les taches de 
			   forme vraiment trop étirées, on incrémente le
			   compteur */
			   nbActuel++;
			   proba = proba - varProba;
			}
		}

	   /* on va à droite ou à gauche */
	   for(j=0; j<pas; j++)
		{

		if(hautDroit == 'o')
			{
			   y++;
			}
		else
			{
			   y--;
			}

		   nbAlea = rand()%100;
		   
		   if ((nbAlea<=proba)&&(nbActuel < nbMax))
			{
			   ajusteCoordCarte(&x, &y, xMax, yMax);

			   /* condition de remplissage : le terrain n'est pas 				   du sable et n'est pas incompatible avec la
			   production à placer */
			   if((1 == cmpTerrainNom(compTerr, "sable"))&&
				(1 == cmpTerrainNom(compTerr, nomTerrainTabou)))
				{
				   setNouvProdCaseCarte(pcarte,x,y,z,nomProdGraine);
				}

			   /* Dans tous les cas, pour éviter les taches de 
			   forme vraiment trop étirées, on incrémente le
			   compteur */
			   nbActuel++;
			   proba = proba - varProba;
			}
		}
	   pas++;

		if(hautDroit == 'o')
			{
			   hautDroit = 'n';
			}
		else
			{
			   hautDroit = 'o';
			}

	}

}

void planterGrainesProdCarte(Carte *pcarte, unsigned int nbGraines, unsigned int z, char *nomNouvProd, unsigned int tailleMax, char *nomTerrainTabou)
{
   unsigned int xAlea, yAlea, maxX, maxY, tailleAlea, i;
   Terrain *compTerr;

   for(i=0; i<nbGraines; i++)
	{

	/* tirage de la taille maximale de la tache (pour l'heure, la taille
	max minimale est de 10 cases) */
	tailleAlea =  10 + rand()%(tailleMax - 9);

	/* Tant que la case n'est pas valide (terrain interdit ou production déjà présente), tirer une case */
	   do
		{
		   maxX = getXCarte(pcarte)-1;
		   maxY = getYCarte(pcarte)-1;
		   xAlea = rand()%maxX+1;
		   yAlea = rand()%maxY+1;

		   compTerr = getTerrainCaseCarte(pcarte, xAlea, yAlea, z);
		}
		while( (cmpTerrainNom(compTerr, "sable") == 1)||
			(cmpTerrainNom(compTerr, nomTerrainTabou) == 1)||
			(NULL != getProdCaseCarte(pcarte, xAlea, yAlea, z)));

	   pousseGraineProdCarte(pcarte, xAlea, yAlea, z, tailleAlea, nomNouvProd, nomTerrainTabou);
	}
}



Carte *genererCarte(unsigned int x, unsigned int y, unsigned int z, unsigned int nbLacs, unsigned int nbGrottes, unsigned int nbForets, unsigned int nbFilonsParStrate,TabTerrains *ptableauTerr)
{
   Carte *resCarte;
   Terrain *pterrain;
   unsigned int tailleLac, tailleGrotte, tailleForet, tailleFilon, i;

   tailleLac = 70;		/* à l'origine : 30 */
   tailleGrotte = 20;		/* à l'origine : 20 */
   tailleForet = 80;
   tailleFilon = 20;

   assert(z>1);

   creerCarte(&resCarte,x,y,z, ptableauTerr);

   /* Génération de la surface */
   pterrain = rechercheTabTerrains(ptableauTerr,"eau");
   planterGrainesCarte(resCarte,nbLacs,0,pterrain,tailleLac);
   sableCarte(resCarte,ptableauTerr);

   /* Génération des sous-sols */
   for(i=1;i<z;i++)
	{
	   pterrain = rechercheTabTerrains(ptableauTerr,"grotte");
	   planterGrainesCarte(resCarte,nbGrottes,i,pterrain,tailleGrotte);
	}

   /* Placement des ressources : forêts */
   planterGrainesProdCarte(resCarte, nbForets, 0, "bois", tailleForet, "eau");

   /* Placement des ressources : filons de métal */
   for(i=1;i<z;i++)
	{
   planterGrainesProdCarte(resCarte, nbFilonsParStrate, i, "metal", tailleFilon, "grotte");
	}

   return resCarte;
}


/*================================== Test ===================================*/

/* fonction à supprimer */
void affiche(Carte *pcarte, unsigned int z)
{
   unsigned int x,y,i,j;
   Terrain *compTerr;
   x = getXCarte(pcarte);
   y = getYCarte(pcarte);

printf("\n");
for(j=0;j<y;j++)
	{
	   for(i=0;i<x;i++)
		{
		   compTerr=getTerrainCaseCarte(pcarte, i, j,z);

		   if(cmpTerrainNom(compTerr,"terreSurf") == 1)
			{
			   if(NULL != getNomProdCaseCarte(pcarte,i,j,z))
				{
					if(0 == strcmp("bois", getNomProdCaseCarte(pcarte,i,j,z)))
					{
					   printf("*");
					}
				}
			   else
				{
				   printf("#");
				}
			}

		   if(cmpTerrainNom(compTerr,"terreSout") == 1)
			{

			   if(NULL != getNomProdCaseCarte(pcarte,i,j,z))
				{

				   if(0 == strcmp("metal", getNomProdCaseCarte(pcarte,i,j,z)))
					{
					   printf("f");
					}
				}
			   else
				{
				   printf("o");
				}
			}

		   if(cmpTerrainNom(compTerr,"grotte") == 1)
			{
			   printf("_");
			}

		   if(cmpTerrainNom(compTerr,"eau") == 1)
			{
			   printf(" ");
			}

		   if(cmpTerrainNom(compTerr,"sable") == 1)
			{
			   printf("s");
			}
		   
		}
	printf("\n");
	}

}




void testCarte()
{
   int i,j,k;
   Terrain *compTerr;
   Carte *carteTest, *carteAdja;
   TabTerrains tableauTerr;
   char *fichierDat = {"DatTerr"};
   unsigned int tabCoord[] = {5,120,210,2,10};
   Case *caseTest;
   char *nomTerr;

   tableauTerr = creerTabTerrains(fichierDat);

   printf("Test de Carte\n");
   printf("\tCréation et initialisation d'une carte\t\t");

   for(i=0;i<5;i++)
	{
	   creerCarte(&carteTest,tabCoord[i],(300-tabCoord[i]),i+1,&tableauTerr);
	   detruireCarte(carteTest);
	}


   creerCarte(&carteTest,150,150,5, &tableauTerr);

   /* Les terrains des cases ont-ils bien été initialisés ? */
   for(k=1; k<5; k++)
	{
	   for(i=0; i<150; i++)
		{
		   for(j=0;j<150;j++)
			{
			   compTerr = getTerrainCaseCarte(carteTest,i,j,k);
			   assert(cmpTerrainNom(compTerr,"terreSout") == 1);
			}
		}
	}

   for(i=0;i<150;i++)
	{
	   for(j=0;j<150;j++)
		{
		   compTerr = getTerrainCaseCarte(carteTest,i,j,0);
		   assert(cmpTerrainNom(compTerr,"terreSurf") == 1);
		}
	}

   printf("OK\n");

   printf("\tAffectation et récupération de valeurs\t\t");
   creerCarte(&carteAdja,3,3,2, &tableauTerr);
   for(i=0;i<3;i++)
	{
	   for(j=0;j<3;j++)
		{
		   compTerr = getTerrainCaseCarte(carteAdja,i,j,0);
		   nomTerr = getNomTerrain(compTerr);
		   compTerr = rechercheTabTerrains(&tableauTerr, "terreSurf");
		   assert(cmpTerrainNom(compTerr, nomTerr) == 1);
		   caseTest = getCaseCarte(carteTest, i,j,0);
		   assert(i == getXCase(caseTest));
		   assert(j == getYCase(caseTest));
		   assert(0 == getZCase(caseTest));
		}
	}

   printf("OK\n");

   detruireCarte(carteTest);

   printf("\tGénération aléatoire de la carte\t\t");
   carteTest = genererCarte(30,30,3,6,8,7,8,&tableauTerr);
   printf("OK\n\n");

   affiche(carteTest, 0);
/*
   printf("\n\n");
   affiche(carteTest, 2);
*/
/* à supprimer */
/*
setNouvProdCaseCarte(carteTest, 2,2,0, "bois");

   if(NULL != getNomProdCaseCarte(carteTest,2,2,0))
	{
	   printf("%s\n",getNomProdCaseCarte(carteTest,2,2,0));
	}
   else
	{
	   printf("Y'en n'a pas.\n");
	}
*/
   detruireCarte(carteTest);
   detruireCarte(carteAdja);

   detruireTabTerrains(&tableauTerr);
}
